package org.ala.tiktools.rpc.kcp.protocol.tools;

import org.ala.tiktools.rpc.kcp.config.RpcKcpConfigInfo;
import org.ala.tiktools.rpc.kcp.protocol.Kcp;

/**
 * rto, resend 相关计算
 *
 * @author ala
 * @date 2025-04-11 23:24
 */
public class KcpRto {


    /**
     *  绑定的kcp
     */
    protected Kcp kcp;
    /**
     *  rto时间
     */
    protected int rxRto, rxSrtt, rxRttvar, rxMinrto;
    /**
     *  Delay模式
     */
    protected boolean noDelay;


    public KcpRto(Kcp kcp, int rxRto, int  rxMinrto, boolean noDelay) {
        this.kcp = kcp;

        this.rxRto = rxRto;
        this.rxMinrto = rxMinrto;

        this.rxSrtt = 0;
        this.rxRttvar = 0;
        this.noDelay = noDelay;
    }


    /**
     * 更新rxRto
     */
    public void updateAck(int rtt) {
        if (rtt < 0) {return;}

        if (rxSrtt == 0) {
            rxSrtt = rtt;
            rxRttvar = rtt / 2;
        } else {
            int delta = rtt - rxSrtt;
            if (delta < 0) {
                delta = -delta;
            }
            rxRttvar = (3 * rxRttvar + delta) / 4;
            rxSrtt = (7 * rxSrtt + rtt) / 8;
            if (rxSrtt < 1) {
                rxSrtt = 1;
            }
        }
        int rto = rxSrtt + Math.max(kcp.getInterval(), 4 * rxRttvar);
        //  可以确定RpcKcpConfigInfo.INSTANCE.getiKcpRtoMax() 是3数中最大的。所以这里取的是 < max 的第一个数
        rxRto = Math.min(Math.max(rxMinrto, rto), RpcKcpConfigInfo.INSTANCE.getiKcpRtoMax());
    }



    public int getRxRto() {
        return rxRto;
    }

    public void setRxRto(int rxRto) {
        this.rxRto = rxRto;
    }

    public int getRxSrtt() {
        return rxSrtt;
    }

    public void setRxSrtt(int rxSrtt) {
        this.rxSrtt = rxSrtt;
    }

    public int getRxRttvar() {
        return rxRttvar;
    }

    public void setRxRttvar(int rxRttvar) {
        this.rxRttvar = rxRttvar;
    }

    public int getRxMinrto() {
        return rxMinrto;
    }

    public void setRxMinrto(int rxMinrto) {
        this.rxMinrto = rxMinrto;
    }

    public boolean isNoDelay() {
        return noDelay;
    }

    public void setNoDelay(boolean noDelay) {
        this.noDelay = noDelay;
    }
}
